using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TradeFlow.Server.Dto;
using TradeFlow.Server.Models;
using SqlSugar;
using TradeFlow.Server.Language;
using RuoVea.ExEnum;

namespace TradeFlow.Server.Service
{
    /// <summary>
    /// 统计报表服务类
    /// </summary>
    public class JxReportService : IApplicationService
    {
        private readonly SugarRepository<JxBillHead> _billHeadRepository;
        private readonly SugarRepository<JxBillList> _billListRepository;
        private readonly SugarRepository<JxGoods> _goodsRepository;
        private readonly ICurrentUser _currentUser;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="billHeadRepository"></param>
        /// <param name="billListRepository"></param>
        /// <param name="goodsRepository"></param>
        /// <param name="currentUser"></param>
        public JxReportService(SugarRepository<JxBillHead> billHeadRepository, SugarRepository<JxBillList> billListRepository, SugarRepository<JxGoods> goodsRepository, ICurrentUser currentUser)
        {
            _billHeadRepository = billHeadRepository;
            _billListRepository = billListRepository;
            _goodsRepository = goodsRepository;
            _currentUser = currentUser;
        }

        /// <summary>
        /// 获取进货明细表
        /// </summary>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="partnerName"></param>
        /// <returns></returns>
        public async Task<RestfulResult<List<PurchaseDetailReport>>> GetPurchaseDetailReportAsync(DateTime? startDate, DateTime? endDate, string partnerName)
        {
            try
            {
                // 先获取符合条件的单据头ID
                var headIds = await _billHeadRepository.AsQueryable()
                    .Where(h => h.Type == "1" || h.Type == "5")
                    .Where(h => !startDate.HasValue || h.BillDate >= (startDate.Value == DateTime.MinValue ? DateTime.MinValue : startDate.Value))
                    .Where(h => !endDate.HasValue || h.BillDate <= (endDate.Value == DateTime.MaxValue ? DateTime.MaxValue : endDate.Value.AddDays(1).AddSeconds(-1)))
                    .Where(h => string.IsNullOrEmpty(partnerName) || h.Partner.Contains(partnerName))
                    .Where(h => h.Creator == _currentUser.UserId)
                    .Select(h => h.Id)
                    .ToListAsync();

                if (headIds.Count == 0)
                {
                    return new RestfulResult<List<PurchaseDetailReport>> { Data = new List<PurchaseDetailReport>() };
                }

                // 根据单据头ID查询明细
                var details = await _billListRepository.AsQueryable()
                    .Where(d => headIds.Contains(d.HeadId))
                    .ToListAsync();

                // 获取对应的单据头信息
                var heads = await _billHeadRepository.AsQueryable()
                    .Where(h => headIds.Contains(h.Id))
                    .ToListAsync();

                // 组合结果
                var result = details.Join(
                    heads,
                    d => d.HeadId,
                    h => h.Id,
                    (d, h) => new PurchaseDetailReport
                    {
                        BillNo = h.BillNo,
                        BillStatus = h.Status,
                        BillDate = h.BillDate.ToString(),
                        PartnerName = h.Partner,
                        ContractNo = h.ContractNo,
                        InvoiceNo = h.InvoiceNo,
                        LogisticsCompany = h.Logistics,
                        LogisticsNo = h.LogisticsNo,
                        HeadRemark = h.Note,
                        GoodsCode = d.Code,
                        GoodsName = d.Name,
                        GoodsCategory = d.Category,
                        Specifications = d.Model,
                        Origin = d.Producer,
                        Unit = d.Unit,
                        Quantity = d.Qty ?? 0,
                        UnitPrice = d.Price ?? 0m,
                        Amount = d.Amount ?? 0m,
                        GoodsRemark = d.Note
                    }).ToList();

                var restful = new RestfulResult<List<PurchaseDetailReport>>() { Code = CodeStatus.OK };
                restful.Data = result;
        return restful;
            }
            catch (Exception ex)
            {
                return new RestfulResult<List<PurchaseDetailReport>> { Code = CodeStatus.BadRequest, Message = ex.Message };
            }
        }

        /// <summary>
        /// 获取进退货明细表
        /// </summary>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="partnerName"></param>
        /// <returns></returns>
        public async Task<RestfulResult<List<PurchaseReturnDetailReport>>> GetPurchaseReturnDetailReportAsync(DateTime? startDate, DateTime? endDate, string partnerName)
        {
            try
            {
                // 先获取符合条件的单据头ID
                var headIds = await _billHeadRepository.AsQueryable()
                    .Where(h => h.Type == "2" || h.Type == "6")
                    .Where(h => !startDate.HasValue || h.BillDate >= startDate.Value)
                    .Where(h => !endDate.HasValue || h.BillDate <= endDate.Value.AddDays(1).AddSeconds(-1))
                    .Where(h => string.IsNullOrEmpty(partnerName) || h.Partner.Contains(partnerName))
                    .Where(h => h.Creator == _currentUser.UserId)
                    .Select(h => h.Id)
                    .ToListAsync();

                if (headIds.Count == 0)
                {
                    return new RestfulResult<List<PurchaseReturnDetailReport>> { Data = new List<PurchaseReturnDetailReport>() };
                }

                // 根据单据头ID查询明细
                var details = await _billListRepository.AsQueryable()
                    .Where(d => headIds.Contains(d.HeadId))
                    .ToListAsync();

                // 获取对应的单据头信息
                var heads = await _billHeadRepository.AsQueryable()
                    .Where(h => headIds.Contains(h.Id))
                    .ToListAsync();

                // 组合结果
                var result = details.Join(
                    heads,
                    d => d.HeadId,
                    h => h.Id,
                    (d, h) => new PurchaseReturnDetailReport
                    {
                        BillNo = h.BillNo,
                        BillStatus = h.Status,
                        BillDate = h.BillDate.ToString(),
                        PartnerName = h.Partner,
                        ContractNo = h.ContractNo,
                        InvoiceNo = h.InvoiceNo,
                        LogisticsCompany = h.Logistics,
                        LogisticsNo = h.LogisticsNo,
                        HeadRemark = h.Note,
                        GoodsCode = d.Code,
                        GoodsName = d.Name,
                        GoodsCategory = d.Category,
                        Specifications = d.Model,
                        Origin = d.Producer,
                        Unit = d.Unit,
                        Quantity = d.Qty ?? 0,
                        UnitPrice = d.Price ?? 0m,
                        Amount = d.Amount ?? 0m,
                        GoodsRemark = d.Note
                    }).ToList();

                var restful = new RestfulResult<List<PurchaseReturnDetailReport>>() { Code = CodeStatus.OK };
        restful.Data = result;
        return restful;
            }
            catch (Exception ex)
            {
                return new RestfulResult<List<PurchaseReturnDetailReport>> { Code = CodeStatus.BadRequest, Message = ex.Message };
            }
        }

        /// <summary>
        /// 获取销货明细表
        /// </summary>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="partnerName"></param>
        /// <returns></returns>
        public async Task<RestfulResult<List<SaleDetailReport>>> GetSaleDetailReportAsync(DateTime? startDate, DateTime? endDate, string partnerName)
        {
            try
            {
                // 先获取符合条件的单据头ID
                var headIds = await _billHeadRepository.AsQueryable()
                    .Where(h => h.Type == "3" || h.Type == "7")
                    .Where(h => !startDate.HasValue || h.BillDate >= startDate.Value)
                    .Where(h => !endDate.HasValue || h.BillDate <= endDate.Value.AddDays(1).AddSeconds(-1))
                    .Where(h => string.IsNullOrEmpty(partnerName) || h.Partner.Contains(partnerName))
                    .Where(h => h.Creator == _currentUser.UserId)
                    .Select(h => h.Id)
                    .ToListAsync();

                if (headIds.Count == 0)
                {
                    return new RestfulResult<List<SaleDetailReport>> { Data = new List<SaleDetailReport>() };
                }

                // 根据单据头ID查询明细
                var details = await _billListRepository.AsQueryable()
                    .Where(d => headIds.Contains(d.HeadId))
                    .ToListAsync();

                // 获取对应的单据头信息
                var heads = await _billHeadRepository.AsQueryable()
                    .Where(h => headIds.Contains(h.Id))
                    .ToListAsync();

                // 组合结果
                var result = details.Join(
                    heads,
                    d => d.HeadId,
                    h => h.Id,
                    (d, h) => new SaleDetailReport
                    {
                        BillNo = h.BillNo,
                        BillStatus = h.Status,
                        BillDate = h.BillDate.ToString(),
                        PartnerName = h.Partner,
                        ContractNo = h.ContractNo,
                        InvoiceNo = h.InvoiceNo,
                        LogisticsCompany = h.Logistics,
                        LogisticsNo = h.LogisticsNo,
                        HeadRemark = h.Note,
                        GoodsCode = d.Code,
                        GoodsName = d.Name,
                        GoodsCategory = d.Category,
                        Specifications = d.Model,
                        Origin = d.Producer,
                        Unit = d.Unit,
                        Quantity = d.Qty ?? 0,
                        UnitPrice = d.Price ?? 0m,
                        Amount = d.Amount ?? 0m,
                        GoodsRemark = d.Note
                    }).ToList();

                var restful = new RestfulResult<List<SaleDetailReport>>() { Code = CodeStatus.OK };
        restful.Data = result;
        return restful;
            }
            catch (Exception ex)
            {
                return new RestfulResult<List<SaleDetailReport>> { Code = CodeStatus.BadRequest, Message = ex.Message };
            }
        }

        /// <summary>
        /// 获取销退货明细表
        /// </summary>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="partnerName"></param>
        /// <returns></returns>
        public async Task<RestfulResult<List<SaleReturnDetailReport>>> GetSaleReturnDetailReportAsync(DateTime? startDate, DateTime? endDate, string partnerName)
        {
            try
            {
                // 先获取符合条件的单据头ID
                var headIds = await _billHeadRepository.AsQueryable()
                    .Where(h => h.Type == "4" || h.Type == "8")
                    .Where(h => !startDate.HasValue || h.BillDate >= startDate.Value)
                    .Where(h => !endDate.HasValue || h.BillDate <= endDate.Value.AddDays(1).AddSeconds(-1))
                    .Where(h => string.IsNullOrEmpty(partnerName) || h.Partner.Contains(partnerName))
                    .Where(h => h.Creator == _currentUser.UserId)
                    .Select(h => h.Id)
                    .ToListAsync();

                if (headIds.Count == 0)
                {
                    return new RestfulResult<List<SaleReturnDetailReport>> { Data = new List<SaleReturnDetailReport>() };
                }

                // 根据单据头ID查询明细
                var details = await _billListRepository.AsQueryable()
                    .Where(d => headIds.Contains(d.HeadId))
                    .ToListAsync();

                // 获取对应的单据头信息
                var heads = await _billHeadRepository.AsQueryable()
                    .Where(h => headIds.Contains(h.Id))
                    .ToListAsync();

                // 组合结果
                var result = details.Join(
                    heads,
                    d => d.HeadId,
                    h => h.Id,
                    (d, h) => new SaleReturnDetailReport
                    {
                        BillNo = h.BillNo,
                        BillStatus = h.Status,
                        BillDate = h.BillDate.ToString(),
                        PartnerName = h.Partner,
                        ContractNo = h.ContractNo,
                        InvoiceNo = h.InvoiceNo,
                        LogisticsCompany = h.Logistics,
                        LogisticsNo = h.LogisticsNo,
                        HeadRemark = h.Note,
                        GoodsCode = d.Code,
                        GoodsName = d.Name,
                        GoodsCategory = d.Category,
                        Specifications = d.Model,
                        Origin = d.Producer,
                        Unit = d.Unit,
                        Quantity = d.Qty ?? 0,
                        UnitPrice = d.Price ?? 0m,
                        Amount = d.Amount ?? 0m,
                        GoodsRemark = d.Note
                    }).ToList();

                var restful = new RestfulResult<List<SaleReturnDetailReport>>() { Code = CodeStatus.OK };
                restful.Data = result;
        return restful;
            }
            catch (Exception ex)
            {
                return new RestfulResult<List<SaleReturnDetailReport>> { Code = CodeStatus.BadRequest, Message = ex.Message };
            }
        }

        /// <summary>
        /// 获取商品利润报表
        /// </summary>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        public async Task<RestfulResult<List<GoodsProfitReport>>> GetGoodsProfitReportAsync(DateTime? startDate, DateTime? endDate)
        {
            try
            {
                // 获取所有商品
                var goodsList = await _goodsRepository.AsQueryable()
                    .Where(g => g.Creator == _currentUser.UserId)
                    .ToListAsync();

                var result = new List<GoodsProfitReport>();

            foreach (var goods in goodsList)
            {
                // 计算进货金额
                var purchaseAmount = await CalculateGoodsAmountAsync(goods.Code, new[] { "1", "5" }, startDate, endDate);
                // 计算进退货金额
                var purchaseReturnAmount = await CalculateGoodsAmountAsync(goods.Code, new[] { "2", "6" }, startDate, endDate);
                // 计算销货金额
                var saleAmount = await CalculateGoodsAmountAsync(goods.Code, new[] { "3", "7" }, startDate, endDate);
                // 计算销退货金额
                var saleReturnAmount = await CalculateGoodsAmountAsync(goods.Code, new[] { "4", "8" }, startDate, endDate);

                // 计算销售利润
                var salesProfit = (saleAmount - saleReturnAmount) - (purchaseAmount - purchaseReturnAmount);

                result.Add(new GoodsProfitReport
                {
                    GoodsCode = goods.Code ?? string.Empty,
                    GoodsName = goods.Name ?? string.Empty,
                    GoodsCategory = goods.Category ?? string.Empty,
                    Specifications = goods.Model ?? string.Empty,
                    Origin = goods.Producer ?? string.Empty,
                    Unit = goods.Unit ?? string.Empty,
                    PurchaseAmount = purchaseAmount,
                    PurchaseReturnAmount = purchaseReturnAmount,
                    SaleAmount = saleAmount,
                    SaleReturnAmount = saleReturnAmount,
                    SalesProfit = salesProfit
                });
                }

                var restful = new RestfulResult<List<GoodsProfitReport>>() { Code = CodeStatus.OK };
        restful.Data = result;
        return restful;
            }
            catch (Exception ex)
            {
                return new RestfulResult<List<GoodsProfitReport>> { Code = CodeStatus.BadRequest, Message = ex.Message };
            }
        }

        /// <summary>
        /// 计算指定商品在指定类型单据中的总金额
        /// </summary>
        /// <param name="goodsCode"></param>
        /// <param name="billTypes"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        private async Task<decimal> CalculateGoodsAmountAsync(string? goodsCode, string[] billTypes, DateTime? startDate, DateTime? endDate)
        {
            // 先获取符合条件的单据头
            var headIds = await _billHeadRepository.AsQueryable()
                .Where(h => billTypes.Contains(h.Type))
                .Where(h => !startDate.HasValue || h.BillDate >= startDate.Value)
                .Where(h => !endDate.HasValue || h.BillDate <= endDate.Value.AddDays(1).AddSeconds(-1))
                .Where(h => h.Creator == _currentUser.UserId)
                .Select(h => h.Id)
                .ToListAsync();

            // 根据单据头ID和商品编码查询明细并计算总金额
            return await _billListRepository.AsQueryable()
                .Where(l => headIds.Contains(l.HeadId) && l.Code == goodsCode)
                .SumAsync(l => l.Amount) ?? 0;
        }

        /// <summary>
        /// 查询单据明细
        /// </summary>
        /// <param name="pageNo"></param>
        /// <param name="pageSize"></param>
        /// <param name="type"></param>
        /// <param name="partner"></param>
        /// <returns></returns>
        public async Task<RestfulResult<PageResult<BillDetailInfo>>> QueryBillDetailsAsync(int pageNo, int pageSize, string? type = null, string? partner = null)
        {
            // 使用SQLSugar实现联表查询
            var query = _billListRepository.AsQueryable()
                .LeftJoin<JxBillHead>((list, head) => list.HeadId == head.Id)
                .Where((list, head) => head.Creator == _currentUser.UserId);

            // 添加过滤条件
            if (!string.IsNullOrEmpty(type))
                query = query.Where((list, head) => head.Type == type);
            if (!string.IsNullOrEmpty(partner))
                query = query.Where((list, head) => head.Partner.Contains(partner));

            // 映射字段
            var result = await query.Select((list, head) => new BillDetailInfo
            {
                SeqNo = list.SeqNo,
                Code = list.Code,
                Name = list.Name,
                Category = list.Category,
                Model = list.Model,
                Producer = list.Producer,
                Unit = list.Unit,
                Qty = list.Qty ?? 0,
                Price = list.Price ?? 0m,
                Amount = list.Amount ?? 0m,
                ListNote = list.Note,
                Type = head.Type,
                BillNo = head.BillNo,
                Status = head.Status,
                BillDate = head.BillDate ?? DateTime.MinValue,
                Partner = head.Partner,
                ContractNo = head.ContractNo,
                InvoiceNo = head.InvoiceNo,
                SettleMode = head.SettleMode,
                TotalAmount = head.TotalAmount ?? 0m,
                Logistics = head.Logistics,
                LogisticsNo = head.LogisticsNo,
                LogisticsFee = head.LogisticsFee ?? 0m,
                ReturnNo = head.ReturnNo,
                Note = head.Note
            }).ToPageAsync(pageNo, pageSize);

            var restful = new RestfulResult<PageResult<BillDetailInfo>>() { Code = CodeStatus.OK };
            restful.Data = result;
            return restful;
        }

        /// <summary>
        /// 查询利润报表
        /// </summary>
        /// <param name="pageNo"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<RestfulResult<List<ProfitInfo>>> QueryProfitsAsync(int pageNo, int pageSize)
        {
            // 获取所有商品
            var goodsList = await _goodsRepository.AsQueryable()
                .Where(u => u.Creator == _currentUser.UserId)
                .ToListAsync();

            var profitList = new List<ProfitInfo>();
            foreach (var goods in goodsList)
            {
                // 计算进货金额
                var importAmount = await CalculateAmountAsync(goods.Code, "进货");
                var importReturnAmount = await CalculateAmountAsync(goods.Code, "进退货");
                var exportAmount = await CalculateAmountAsync(goods.Code, "销货");
                var exportReturnAmount = await CalculateAmountAsync(goods.Code, "销退货");

                // 计算利润
                var profit = (exportAmount - exportReturnAmount) - (importAmount - importReturnAmount);

                profitList.Add(new ProfitInfo
                {
                    Code = goods.Code ?? string.Empty,
                    Name = goods.Name ?? string.Empty,
                    Category = goods.Category ?? string.Empty,
                    Model = goods.Model ?? string.Empty,
                    Producer = goods.Producer ?? string.Empty,
                    Unit = goods.Unit ?? string.Empty,
                    ImportAmount = importAmount,
                    ImportReturnAmount = importReturnAmount,
                    ExportAmount = exportAmount,
                    ExportReturnAmount = exportReturnAmount,
                    Profit = profit
                });
            }

            // 返回分页数据
            var items = profitList.Skip((pageNo - 1) * pageSize).Take(pageSize).ToList();
            var restful = new RestfulResult<List<ProfitInfo>>() { Code = CodeStatus.OK, Data = items };
            // 添加分页信息到消息字段
            restful.Message = $"{profitList.Count}|{pageNo}|{pageSize}";
            return restful;
        }

        /// <summary>
        /// 计算指定商品在指定类型单据中的总金额
        /// </summary>
        /// <param name="goodsCode"></param>
        /// <param name="billType"></param>
        /// <returns></returns>
        private async Task<decimal> CalculateAmountAsync(string? goodsCode, string? billType)
        {
            return await _billListRepository.AsQueryable()
                .LeftJoin<JxBillHead>((list, head) => list.HeadId == head.Id)
                .Where((list, head) => 
                    list.Code == goodsCode && 
                    head.Type == billType &&
                    head.Status != "作废" &&
                    head.Creator == _currentUser.UserId)
                .Select(list => list.Amount ?? 0)
                .SumAsync(x => x);
        }

        #region 报表数据模型

        /// <summary>
        /// 进货明细表
        /// </summary>
        public class PurchaseDetailReport
        {
            /// <summary>
            /// 进货单号
            /// </summary>
            public string? BillNo { get; set; }

            /// <summary>
            /// 单证状态
            /// </summary>
            public string? BillStatus { get; set; }

            /// <summary>
            /// 进货日期
            /// </summary>
            public string? BillDate { get; set; }

            /// <summary>
            /// 供应商
            /// </summary>
            public string? PartnerName { get; set; }

            /// <summary>
            /// 合同号
            /// </summary>
            public string? ContractNo { get; set; }

            /// <summary>
            /// 发票号
            /// </summary>
            public string? InvoiceNo { get; set; }

            /// <summary>
            /// 物流公司
            /// </summary>
            public string? LogisticsCompany { get; set; }

            /// <summary>
            /// 物流单号
            /// </summary>
            public string? LogisticsNo { get; set; }

            /// <summary>
            /// 表头备注
            /// </summary>
            public string? HeadRemark { get; set; }

            /// <summary>
            /// 商品编码
            /// </summary>
            public string? GoodsCode { get; set; }

            /// <summary>
            /// 商品名称
            /// </summary>
            public string? GoodsName { get; set; }

            /// <summary>
            /// 商品类别
            /// </summary>
            public string? GoodsCategory { get; set; }

            /// <summary>
            /// 规格型号
            /// </summary>
            public string? Specifications { get; set; }

            /// <summary>
            /// 产地
            /// </summary>
            public string? Origin { get; set; }

            /// <summary>
            /// 计量单位
            /// </summary>
            public string? Unit { get; set; }

            /// <summary>
            /// 数量
            /// </summary>
            public int Quantity { get; set; }

            /// <summary>
            /// 单价
            /// </summary>
            public decimal UnitPrice { get; set; }

            /// <summary>
            /// 金额
            /// </summary>
            public decimal Amount { get; set; }

            /// <summary>
            /// 商品备注
            /// </summary>
            public string? GoodsRemark { get; set; }
        }

        /// <summary>
        /// 进退货明细表
        /// </summary>
        public class PurchaseReturnDetailReport : PurchaseDetailReport
        {
            // 继承PurchaseDetailReport的所有属性
        }

        /// <summary>
        /// 销货明细表
        /// </summary>
        public class SaleDetailReport : PurchaseDetailReport
        {
            // 继承PurchaseDetailReport的所有属性
        }

        /// <summary>
        /// 销退货明细表
        /// </summary>
        public class SaleReturnDetailReport : PurchaseDetailReport
        {
            // 继承PurchaseDetailReport的所有属性
        }

        /// <summary>
        /// 商品利润表
        /// </summary>
        public class GoodsProfitReport
        {
            /// <summary>
            /// 商品编码
            /// </summary>
            public string? GoodsCode { get; set; }

            /// <summary>
            /// 商品名称
            /// </summary>
            public string? GoodsName { get; set; }

            /// <summary>
            /// 商品类别
            /// </summary>
            public string? GoodsCategory { get; set; }

            /// <summary>
            /// 规格型号
            /// </summary>
            public string? Specifications { get; set; }

            /// <summary>
            /// 产地
            /// </summary>
            public string? Origin { get; set; }

            /// <summary>
            /// 计量单位
            /// </summary>
            public string? Unit { get; set; }

            /// <summary>
            /// 进货金额
            /// </summary>
            public decimal PurchaseAmount { get; set; }

            /// <summary>
            /// 进退货金额
            /// </summary>
            public decimal PurchaseReturnAmount { get; set; }

            /// <summary>
            /// 销货金额
            /// </summary>
            public decimal SaleAmount { get; set; }

            /// <summary>
            /// 销退货金额
            /// </summary>
            public decimal SaleReturnAmount { get; set; }

            /// <summary>
            /// 销售利润
            /// </summary>
            public decimal SalesProfit { get; set; }
        }

        #endregion
    }
}